#pragma once
#include <iostream>


template<class T>
class Point2
{
public:
    Point2();
    Point2(T x, T y);
    Point2(const Point2& pt);
    Point2& operator=(const Point2 &pt);
    const Point2 operator+(const Point2 &pt);
    const Point2 operator-(const Point2 &pt);
    friend const Point2 operator*(const Point2 &pt, T a);
    friend const Point2 operator*(T a, const Point2 &pt);
    friend const Point2 operator/(const Point2 &pt, T a);
    const Point2& operator+=(const Point2 &pt);
    const Point2& operator-=(const Point2 &pt);
    const Point2& operator*=(T a);
    const Point2& operator/=(T a);
    const bool operator==(const Point2 &pt);
    const bool operator!=(const Point2 &pt);
    friend std::ostream &operator<<(std::ostream &out, const Point2 &pt);
public:
    T x, y;
};


template<class T>
class Point3
{
public:
    Point3();
    Point3(T x, T y, T z);
    Point3(const Point3& pt);
    Point3& operator=(const Point3 &pt);
    const Point3 operator+(const Point3 &pt);
    const Point3 operator-(const Point3 &pt);
    friend const Point3 operator*(const Point3 &pt, T a);
    friend const Point3 operator*(T a, const Point3 &pt);
    friend const Point3 operator/(const Point3 &pt, T a);
    const Point3& operator+=(const Point3 &pt);
    const Point3& operator-=(const Point3 &pt);
    const Point3& operator*=(T a);
    const Point3& operator/=(T a);
    const bool operator==(const Point3 &pt);
    const bool operator!=(const Point3 &pt);
    friend std::ostream &operator<<(std::ostream &out, const Point3 &pt);
public:
    T x, y, z;
};


template<class T>
Point2<T>::Point2(){}


template<class T>
Point2<T>::Point2(T x, T y)
{
    this->x = x;
    this->y = y;
}


template<class T>
Point2<T>::Point2(const Point2& pt)
{
    this->x = pt.x;
    this->y = pt.y;
}


template<class T>
Point2<T>& Point2<T>::operator=(const Point2 &pt)
{
    this->x = pt.x;
    this->y = pt.y;
    return *this;
}


template<class T>
const Point2<T> Point2<T>::operator+(const Point2 &pt)
{
    Point2<T> plus;
    plus.x = this->x + pt.x;
    plus.y = this->y + pt.y;
    return plus;
}


template<class T>
const Point2<T> Point2<T>::operator-(const Point2 &pt)
{
    Point2<T> minus;
    minus.x = this->x + pt.x;
    minus.y = this->y + pt.y;
    return minus;
}


template<class T>
const Point2<T>& Point2<T>::operator+=(const Point2 &pt)
{
    this->x += pt.x;
    this->y += pt.y;
    return *this;
}


template<class T>
const Point2<T>& Point2<T>::operator-=(const Point2 &pt)
{
    this->x -= pt.x;
    this->y -= pt.y;
    return *this;
}


template<class T>
const bool Point2<T>::operator==(const Point2 &pt)
{
    return ((this->x==pt.x)&&(this->y==pt.y));
}


template<class T>
const bool Point2<T>::operator!=(const Point2 &pt)
{
    return ((this->x!=pt.x)||(this->y!=pt.y));
}


template<class T>
const Point2<T> operator*(const Point2<T> &pt, T a)
{
    Point2<T> multiply;
    multiply.x = pt.x * a;
    multiply.y = pt.y * a;
    return multiply;
}


template<class T>
const Point2<T> operator*(T a, const Point2<T> &pt)
{
    Point2<T> multiply;
    multiply.x = pt.x * a;
    multiply.y = pt.y * a;
    return multiply;
}


template<class T>
const Point2<T> operator/(const Point2<T> &pt, T a)
{
    Point2<T> division;
    division.x = pt.x / a;
    division.y = pt.y / a;
    return division;
}


template<class T>
const Point2<T>& Point2<T>::operator*=(T a)
{
    this->x *= a;
    this->y *= a;
    return *this;
}


template<class T>
const Point2<T>& Point2<T>::operator/=(T a)
{
    this->x /= a;
    this->y /= a;
    return *this;
}


template<class T>
const std::ostream &operator<<(std::ostream &out, const Point2<T> &pt)
{
    out << "(" << pt.x << "," << pt.y << ")";
    return out;
}


template<class T>
Point3<T>::Point3(){}


template<class T>
Point3<T>::Point3(T x, T y, T z)
{
    this->x = x;
    this->y = y;
    this->z = z;
}


template<class T>
Point3<T>::Point3(const Point3& pt)
{
    this->x = pt.x;
    this->y = pt.y;
    this->z = pt.z;
}


template<class T>
Point3<T>& Point3<T>::operator=(const Point3 &pt)
{
    this->x = pt.x;
    this->y = pt.y;
    this->z = pt.z;
    return *this;
}


template<class T>
const Point3<T> Point3<T>::operator+(const Point3 &pt)
{
    Point3<T> plus;
    plus.x = this->x + pt.x;
    plus.y = this->y + pt.y;
    plus.z = this->z + pt.z;
    return plus;
}


template<class T>
const Point3<T> Point3<T>::operator-(const Point3 &pt)
{
    Point3<T> minus;
    minus.x = this->x + pt.x;
    minus.y = this->y + pt.y;
    minus.z = this->z + pt.z;
    return minus;
}


template<class T>
const Point3<T>& Point3<T>::operator+=(const Point3 &pt)
{
    this->x += pt.x;
    this->y += pt.y;
    this->z += pt.z;
    return *this;
}


template<class T>
const Point3<T>& Point3<T>::operator-=(const Point3 &pt)
{
    this->x -= pt.x;
    this->y -= pt.y;
    this->z -= pt.z;
    return *this;
}


template<class T>
const bool Point3<T>::operator==(const Point3 &pt)
{
    return ((this->x==pt.x)&&(this->y==pt.y)&&(this->z==pt.z));
}


template<class T>
const bool Point3<T>::operator!=(const Point3 &pt)
{
    return ((this->x!=pt.x)||(this->y!=pt.y)||(this->z!=pt.z));
}


template<class T>
const Point3<T> operator*(const Point3<T> &pt, T a)
{
    Point3<T> multiply;
    multiply.x = pt.x * a;
    multiply.y = pt.y * a;
    multiply.z = pt.z * a;
    return multiply;
}


template<class T>
const Point3<T> operator*(T a, const Point3<T> &pt)
{
    Point3<T> multiply;
    multiply.x = pt.x * a;
    multiply.y = pt.y * a;
    multiply.z = pt.z * a;
    return multiply;
}


template<class T>
const Point3<T> operator/(const Point3<T> &pt, T a)
{
    Point3<T> division;
    division.x = pt.x / a;
    division.y = pt.y / a;
    multiply.z = pt.z / a;
    return division;
}


template<class T>
const Point3<T>& Point3<T>::operator*=(T a)
{
    this->x *= a;
    this->y *= a;
    this->z *= a;
    return *this;
}


template<class T>
const Point3<T>& Point3<T>::operator/=(T a)
{
    this->x /= a;
    this->y /= a;
    this->z /= a;
    return *this;
}


template<class T>
const std::ostream &operator<<(std::ostream &out, const Point3<T> &pt)
{
    out << "(" << pt.x << "," << pt.y << "," << pt.z << ")";
    return out;
}
